package com.hzw.saas.web.app.product.controller;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hzw.saas.api.product.ILicenseUserService;
import com.hzw.saas.api.product.IProductPaperService;
import com.hzw.saas.api.product.IProductService;
import com.hzw.saas.api.product.IUserProductService;
import com.hzw.saas.api.product.bo.ProductLiteratureBO;
import com.hzw.saas.api.product.dto.ProductDetailsDto;
import com.hzw.saas.api.product.dto.ProductDto;
import com.hzw.saas.api.product.dto.UserProductAuthDto;
import com.hzw.saas.api.product.dto.UserProductDto;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.security.pojo.dto.SaasUser;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.web.app.product.dto.ProductLiteratureDto;
import com.hzw.saas.web.app.product.param.ProductSubscribeParam;
import com.hzw.saas.web.app.product.param.ProductUsageParam;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品 前端控制器
 * </p>
 *
 * @author sonam
 * @since 2021-01-19
 */
@RestController
@RequestMapping
@RequiredArgsConstructor
@Validated
@Api(tags = "产品中心")
public class ProductController {

    private final IProductService productService;
    private final IUserProductService userProductService;
    private final ILicenseUserService licenseUserService;

    @Resource(name = "productLiteratureService")
    private IProductPaperService productLiteratureService;

    @GetMapping("/products")
    @SysLog
    @ApiImplicitParams({
        @ApiImplicitParam(name = "cloudType", value = "产品云类型，1:软件云，2:工具云，3:算力云，4:数据云", paramType = "query", dataType = "int", allowMultiple = true)
    })
    @ApiOperation(value = "根据产品类型查询产品列表", notes = "获取所有产品列表，支持分页，可在用户未登录状态调用")
    public ResponseEntity<IPage<ProductDto>> getAllProductsByCloudType(PageParam pageParam, Integer[] cloudType) {
        IPage<ProductDto> productPage = productService.getProductsByCloudTypes(pageParam, cloudType);
        return ResponseEntity.ok(productPage);
    }

    @GetMapping("/products/usage")
    @SysLog
    @ApiOperation(value = "获取用户产品列表", notes = "根据用户所持有的license获取产品列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "cloudType", value = "产品云类型，1:软件云，2:工具云，3:算力云，4:数据云", paramType = "query", dataType = "int", allowMultiple = true)
    })
    public ResponseEntity<List<UserProductAuthDto>> listProductsByUsedAndType(ProductUsageParam productUsageParam) {
        SaasUser user = SecurityUtils.getUser();
        List<UserProductAuthDto> products = licenseUserService.listProducts(user.getUserId(), productUsageParam.getCloudType());
        return ResponseEntity.ok(products);
    }

    @GetMapping("/product/{productId}")
    @SysLog
    @ApiOperation(value = "产品详情", notes = "产品详情")
    public ResponseEntity<ProductDetailsDto> getProductById(@PathVariable String productId) {
        return ResponseEntity.ok(productService.getProductDetailById(productId));
    }

    @GetMapping("/products/usage/count")
    @SysLog
    @ApiOperation(value = "统计产品订阅/未订阅数量", notes = "统计产品订阅/未订阅数量", hidden = true)
    @ApiImplicitParams({
        @ApiImplicitParam(name = "subStatus", value = "产品订阅状态，0:未订阅使用，1:已订阅使用", required = true, paramType = "query"),
    })
    @ApiResponses({
        @ApiResponse(code = 200, message = "已订阅/未订阅数量", response = Integer.class)
    })
    @Deprecated
    public ResponseEntity<Integer> countProductsBySubStatus(@NotNull(message = "订阅状态不可为空") Integer subStatus) {
        SaasUser user = SecurityUtils.getUser();
        int userProductCount = userProductService.countUserProduct(user.getUserId(), subStatus);
        return ResponseEntity.ok(userProductCount);
    }

    @PostMapping("/products/subscribe")
    @SysLog(operation = "订阅/取消订阅产品", mode = 3)
    @ApiOperation(value = "订阅/取消订阅产品", notes = "订阅/取消订阅产品", hidden = true)
    @ApiResponse(code = 200, message = "订阅成功")
    @Deprecated
    public ResponseEntity<Void> subscribeProduct(@Validated ProductSubscribeParam param) {
        SaasUser user = SecurityUtils.getUser();
        UserProductDto userProductDto = new UserProductDto();
        userProductDto.setUserId(user.getUserId())
            .setProductId(param.getProductId())
            .setSubStatus(param.getSubStatus());
        if (Objects.equals(userProductDto.getSubStatus(), 1)) {
            // FIXME: ZZL@02/21/2021 此处license暂时设置未1年
            userProductDto.setLicenseExpireDate(DateUtil.offsetMonth(new Date(), 12));
        }
        userProductService.subscribe(userProductDto);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/product/{productId}/sub-status")
    @SysLog
    @ApiOperation(value = "产品订阅状态", notes = "获取产品订阅状态", hidden = true)
    @ApiResponses({
        @ApiResponse(code = 200, message = "产品订阅状态，1-已订阅，0-为订阅", response = Integer.class)
    })
    @Deprecated
    public ResponseEntity<Integer> getSubStatus(@PathVariable String productId) {
        SaasUser user = SecurityUtils.getUser();
        UserProductDto userProduct = this.userProductService.getUserProduct(user.getUserId(), productId);
        int subStatus = userProduct.getSubStatus() == null ? 0 : userProduct.getSubStatus();
        return ResponseEntity.ok(subStatus);
    }

    @ApiOperationSort(5)
    @GetMapping("/product/paper/{productId}")
    @SysLog(operation = "根据产品id获取相关文献")
    @ApiOperation(value = "根据产品id获取相关文献")
    public ResponseEntity<List<ProductLiteratureDto>> getProductLiterature(@PathVariable("productId") String productId) {
        List<ProductLiteratureBO> byProductId = productLiteratureService.findByProductId(productId);
        if (CollectionUtil.isNotEmpty(byProductId)) {
            ArrayList<ProductLiteratureDto> productLiteratureDtos = new ArrayList<>();
            Map<Integer, List<ProductLiteratureBO>> collect = byProductId.stream().collect(Collectors.groupingBy(ProductLiteratureBO::getPubYear));
            collect.forEach((s, productLiteratureBOS) -> {
                ProductLiteratureDto productLiteratureDto = new ProductLiteratureDto();
                productLiteratureDto.setPubYear(s);
                productLiteratureDto.setProductLiteratureBOS(productLiteratureBOS);
                productLiteratureDtos.add(productLiteratureDto);
            });
            List<ProductLiteratureDto> productLiteratureDtoList = productLiteratureDtos.stream().sorted(Comparator.comparing(ProductLiteratureDto::getPubYear).reversed()).collect(Collectors.toList());
            return ResponseEntity.ok(productLiteratureDtoList);
        }
        return ResponseEntity.ok(Collections.emptyList());
    }
}
